package com.example.cachewebview

import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.http.SslError
import android.os.*
import android.text.TextUtils
import android.util.Log
import android.view.KeyEvent
import android.view.View
import android.view.ViewGroup
import android.webkit.*
import android.widget.FrameLayout
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import com.example.cachewebview.bean.WebNavigationBean
import com.example.cachewebview.bean.WebPaintBean
import com.example.cachewebview.bean.WebPerfBean
import com.example.cachewebview.bean.WebPerformanceBean
import com.example.cachewebview.util.UrlManager
import com.fan.cachewebview.R
import com.fan.cachewebview.core.CacheConfig
import com.fan.cachewebview.core.CacheMode
import com.fan.cachewebview.core.filter.CacheMimeTypeFilter
import com.fan.cachewebview.pool.CacheWebView
import com.fan.cachewebview.pool.WebViewCacheHolder
import com.fan.cachewebview.utils.ImgUtils
import com.google.gson.Gson
import com.google.gson.JsonSyntaxException
import com.google.gson.reflect.TypeToken
import java.io.File
import java.lang.ref.WeakReference

class WebActivity : AppCompatActivity() {
    private lateinit var webView: CacheWebView
    private lateinit var imgViewCache: ImageView
    private lateinit var flGroup: FrameLayout

    private var targetUrl: String = ""


    private val mHandler = MyHandler(WeakReference(this@WebActivity))
    private class MyHandler(val mActivity: WeakReference<WebActivity>) :
        Handler(Looper.getMainLooper()) {}

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_web)
        targetUrl = intent.getStringExtra("url").toString()

        initView()
        initWebSettings()
        cacheImageCheck()
        initWebCacheAndLoad()
    }


    private fun initView() {
        flGroup = findViewById(R.id.fl)

        webView = WebViewCacheHolder.acquire(this)
        val params = FrameLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT
        )

        flGroup.addView(webView, params)

        // 初始化 Image缓存页
        imgViewCache = ImageView(this)
        imgViewCache.visibility = View.GONE
        flGroup.addView(imgViewCache, params)
    }

    private fun initWebSettings() {
        // 基础配置
        val webSettings: WebSettings = webView.settings
        webSettings.javaScriptCanOpenWindowsAutomatically = true
        webSettings.javaScriptEnabled = true
        webSettings.allowFileAccess = true
        webSettings.loadWithOverviewMode = true
        webSettings.layoutAlgorithm = WebSettings.LayoutAlgorithm.SINGLE_COLUMN
        webSettings.useWideViewPort = true
        webSettings.domStorageEnabled = true
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
            webView.settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
        }
        webSettings.blockNetworkImage = true
        webView.addJavascriptInterface(this, "web")
    }


    private fun initWebCacheAndLoad() {
        // 网络缓存模式配置
        val cacheMode =
            if (WebSettingUtil.isNetworkConnected(this)) WebSettings.LOAD_DEFAULT else WebSettings.LOAD_CACHE_ELSE_NETWORK
        webView.settings.cacheMode = cacheMode
        val config: CacheConfig = CacheConfig.Builder(this)
            .setCacheDir(cacheDir.toString() + File.separator + "custom")
            .setDiskCacheSize(200 * 1024 * 1024)
            .setExtensionFilter(CustomMimeTypeFilter())
            .build()
        webView.setCacheMode(CacheMode.CACHE, config)
        webView.webViewClient = mWebViewClient
        webView.loadUrl(targetUrl)
    }


    private val mWebViewClient: WebViewClient = object : WebViewClient() {
        override fun onReceivedError(
            view: WebView?,
            request: WebResourceRequest?,
            error: WebResourceError?
        ) {
            super.onReceivedError(view, request, error)
        }

        override fun shouldInterceptRequest(
            view: WebView?,
            url: String?
        ): WebResourceResponse? {
            return super.shouldInterceptRequest(view, url)
        }

        override fun onPageFinished(view: WebView, url: String) {
            super.onPageFinished(view, url)
            // 将图片拦截设为false
            view.settings.blockNetworkImage = false
            // 性能监控
            view.evaluateJavascript(UrlManager.JS_MONITOR, null)
            // 截图取Bitmap
            if (!TextUtils.isEmpty(url)) {
                if (url == UrlManager.webUrl) {
                    cacheImgLogic(100, url)
                }
            }
        }

        override fun onReceivedSslError(view: WebView, handler: SslErrorHandler, error: SslError) {
            // 接受所有网站的证书
            handler.proceed()
        }
    }


    /**
     * 保存截图
     *
     * @param millis
     * 截图延时时间
     */
    private fun cacheImgLogic(millis: Int, url: String) {
        try {
            if (webView != null && webView.width > 0 && webView.height > 0) {
                val myBitmap: Bitmap = ImgUtils.getViewBitmap(webView)
                if (myBitmap != null) {
                    if (ImgUtils.checkPictureIsSameColor(myBitmap)) {
                        savePictureWhenDiff(myBitmap, url)
                    } else {
                        mHandler.postDelayed(Runnable {
                            if (this@WebActivity.isFinishing) {
                                return@Runnable
                            }
                            saveScreenShot(url)
                            imgViewCache.visibility = View.GONE
                        }, millis.toLong())
                    }
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }


    private fun cacheImageCheck() {
        var path = ""
//        if (targetUrl == UrlManager.webUrl) {
        path = ImgUtils.getImageFromCache(this@WebActivity, UrlManager.webContent)
//        }

        if (!TextUtils.isEmpty(path)) {
            val bm = BitmapFactory.decodeFile(path)
            if (bm != null) {
                imgViewCache.visibility = View.VISIBLE
                imgViewCache.setImageBitmap(bm)
            }
            mHandler.postDelayed(Runnable {
                if (this@WebActivity.isFinishing) {
                    return@Runnable
                }
                imgViewCache.visibility = View.GONE
            }, 6000)
        } else {
            imgViewCache.visibility = View.GONE
        }
    }

    /**
     * 直到加载
     */
    private fun savePictureWhenDiff(bitmap: Bitmap, curUrl: String) {
        mHandler.postDelayed(Runnable {
            if (this@WebActivity.isFinishing) {
                return@Runnable
            }
            if (!ImgUtils.checkPictureIsSameColor(bitmap)) {
                saveScreenShot(curUrl)
                imgViewCache.visibility = View.GONE
            } else {
                savePictureWhenDiff(ImgUtils.getViewBitmap(webView), curUrl)
            }
        }, 70)
    }


    private fun saveScreenShot(curUrl: String) {
        if (!TextUtils.isEmpty(curUrl)) {
            if (curUrl == UrlManager.webUrl) {
                ImgUtils.saveImageToCache(this, ImgUtils.getViewBitmap(webView), UrlManager.webContent)
            }
        }
    }


    override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            if (webView.canGoBack()) {
                webView.goBack()
                return true
            }
        }
        return super.onKeyDown(keyCode, event)
    }


    // 性能监控
    @JavascriptInterface
    fun setH5Performance(timing: String?, curUrl: String?, paint: String?, navigation: String?) {
        try {
            // timing 处理
            val bean: WebPerformanceBean = Gson().fromJson(timing, WebPerformanceBean::class.java)
            var event = WebPerfBean()
            // paint 处理
            if (!TextUtils.isEmpty(paint)) {
                var webFpFcpBeans: List<WebPaintBean>? = null
                try {
                    val userListType = object : TypeToken<List<WebPaintBean?>?>() {}.type
                    webFpFcpBeans = Gson().fromJson<List<WebPaintBean>>(paint, userListType)
                } catch (e: JsonSyntaxException) {
                    e.printStackTrace()
                }

                if (webFpFcpBeans != null && webFpFcpBeans.size > 1) {
                    event.fp = (webFpFcpBeans[0].startTime).toLong()
                    event.fcp = webFpFcpBeans[0].startTime.toLong()

                    if (event.fp < 0) {
                        event.fp = bean.domInteractive - bean.navigationStart
                    }
                    if (event.fcp < 0) {
                        event.fcp = bean.loadEventEnd - bean.navigationStart
                    }

                } else {
                    event.fp = bean.domInteractive - bean.navigationStart
                    event.fcp = bean.loadEventEnd - bean.navigationStart
                }

            } else {
                event.fp = bean.domInteractive - bean.navigationStart
                event.fcp = bean.loadEventEnd - bean.navigationStart
            }
            // navigation 处理
            if (!TextUtils.isEmpty(navigation)) {
                var webNavigationBeans: List<WebNavigationBean>? = null
                try {
                    val userListType = object : TypeToken<List<WebNavigationBean?>?>() {}.type
                    webNavigationBeans =
                        Gson().fromJson<List<WebNavigationBean>>(navigation, userListType)
                } catch (e: JsonSyntaxException) {
                    e.printStackTrace()
                }
                if (webNavigationBeans != null && webNavigationBeans.isNotEmpty()) {
                    event.du = webNavigationBeans[0].duration.toLong()
                } else {
                    event.du = bean.loadEventEnd - bean.navigationStart
                }
            } else {
                event.du = bean.loadEventEnd - bean.navigationStart
            }

            // 可新增dns、tcp、ttfbTime 等
            Log.d("fanLoad", event.toString())

        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    override fun onDestroy() {
        if (webView != null) {
            WebViewCacheHolder.release(webView)
        }
        super.onDestroy()
    }

    class CustomMimeTypeFilter internal constructor() : CacheMimeTypeFilter() {
        init {
//            addMimeType("text/html")
        }
    }

}